﻿using System.Collections.Generic;
using FlowCanvas;
using FlowCanvas.Nodes;
using LogSystem;
using NodeCanvas.Framework;
using ParadoxNotion;
using ParadoxNotion.Design;
using UnityEngine;

namespace Yoozoo.Gameplay.Liberty.Nodes
{
    [Category("Ggame")]
    public class BoxTrigger : EventNode
    {
        public static Transform BlueprintTriggerRoot;
        public static Dictionary<string, Collider> BlueprintTriggers = new Dictionary<string, Collider>();

        [RequiredField]
        public BBParameter<string> pointName;

        public BBParameter<float> radius = 0;

        public BBParameter<Vector3> size = new Vector3(1,1,1);

        public BBParameter<bool> flowTrigger = true;

        protected GameObject target;

        protected FlowOutput onEnter;
        protected FlowOutput onStay;
        protected FlowOutput onExit;
        protected GameObject other;

        public override string name
        {
            get
            {
                return string.Format("{0} ({1})", "BoxTrigger", pointName.value);
            }
        }

        protected override void RegisterPorts()
        {
            AddFlowInput("start", OnStart);

            onEnter = AddFlowOutput("Enter");
            onStay = AddFlowOutput("Stay");
            onExit = AddFlowOutput("Exit");

            AddValueOutput<GameObject>("Other", () => { return other; });
        }

        private void Subscribe(ParadoxNotion.Services.EventRouter router)
        {
            router.onTriggerEnter += OnTriggerEnter;
            router.onTriggerStay += OnTriggerStay;
            router.onTriggerExit += OnTriggerExit;
        }

        private void UnSubscribe(ParadoxNotion.Services.EventRouter router)
        {
            router.onTriggerEnter -= OnTriggerEnter;
            router.onTriggerStay -= OnTriggerStay;
            router.onTriggerExit -= OnTriggerExit;
        }

        void OnTriggerEnter(ParadoxNotion.EventData<Collider> msg)
        {
            OnTriggerEnterFunc(msg);
        }

        protected virtual void OnTriggerEnterFunc(ParadoxNotion.EventData<Collider> msg)
        {
            this.other = msg.value.gameObject;
            onEnter.Call(new Flow());
        }

        void OnTriggerStay(ParadoxNotion.EventData<Collider> msg)
        {
            OnTriggerStayFunc(msg);
        }

        protected virtual void OnTriggerStayFunc(ParadoxNotion.EventData<Collider> msg)
        {
            this.other = msg.value.gameObject;
            onStay.Call(new Flow());
        }

        void OnTriggerExit(ParadoxNotion.EventData<Collider> msg)
        {
            OnTriggerExitFunc(msg);
        }

        protected virtual void OnTriggerExitFunc(ParadoxNotion.EventData<Collider> msg)
        {
            this.other = msg.value.gameObject;
            onExit.Call(new Flow());
        }

        private void ShowTrigger()
        {
            var point = BlueprintUtils.GetBlueprintPoint(pointName.value);
            if (point == null)
            {
                Debug.LogError(LogModule.Blueprint, "找不到蓝图点：" + pointName.value);
                return;
            }

            if (BlueprintTriggers.ContainsKey(pointName.value))
            {
                Debug.LogError(LogModule.Blueprint, "触发器名称重复：" + pointName.value);
                return;
            }

            if (BlueprintTriggerRoot == null)
            {
                BlueprintTriggerRoot = new GameObject("BlueprintTriggerRoot").transform;
            }

            target = new GameObject("BoxTrigger_" + pointName);
            target.transform.parent = BlueprintTriggerRoot;
            target.transform.position = point.position;
            target.transform.eulerAngles = point.eulerAngles;

            BoxCollider boxCollider = target.AddComponent<BoxCollider>();
            boxCollider.isTrigger = true;
            boxCollider.size = size.value;

            BlueprintTriggers[pointName.value] = boxCollider;

            Subscribe(target.GetAddComponent<ParadoxNotion.Services.EventRouter>());
        }

        public void OnStart(Flow f)
        {
            ShowTrigger();
        }

        public override void OnPostGraphStarted()
        {
            if (!flowTrigger.value)
            {
                ShowTrigger();
            }
        }

        public override void OnPostGraphStoped()
        {
            if (target)
            {
                var router = target.GetComponent<ParadoxNotion.Services.EventRouter>();
                if (router != null) { UnSubscribe(router); }

                if (BlueprintTriggers.ContainsKey(pointName.value))
                {
                    BlueprintTriggers.Remove(pointName.value);
                }
                GameObject.DestroyImmediate(target);
            }
        }
    }
}
